(function(){  
var cache = {};  
  
this.Template = function tmpl(str, data){  
  var fn = !/\W/.test(str) ?  
	cache[str] = cache[str] ||  
	  tmpl(document.getElementById(str).innerHTML):  
	new Function("obj",  
	  "var p=[],print=function(){p.push.apply(p,arguments);};" +  
		
	  "with(obj){p.push('" +  
		
	  str  
		.replace(/[\r\t\n]/g, " ")  
		.split("<#").join("\t")  
		.replace(/((^|#>)[^\t]*)'/g, "$1\r")  
		.replace(/\t=(.*?)#>/g, "',$1,'")  
		.split("\t").join("');")  
		 .split("#>").join("p.push('")  
		 .split("\r").join("\\'")  
	 + "');}return p.join('');");  
	 
   return data ? fn( data ): fn;  
 };  
})(); 

Class.Mutators.Binds = function(binds){
	if (!this.prototype.initialize) this.implement('initialize', function(){});
	return Array.from(binds).concat(this.prototype.Binds || []);
};

Class.Mutators.initialize = function(initialize){
	return function(){
		Array.from(this.Binds).each(function(name){
			var original = this[name];
			if (original) this[name] = original.bind(this);
		}, this);
		return initialize.apply(this, arguments);
	};
};

Array.implement({
    count: function () {
        return this.length;
    },
    random: function (n) {
        var result = [],
            ghost = this.slice(0),
            len = ghost.length;
        n = (n|0).limit(1, len);
        while (n-- > 0) {
            result.push(ghost.splice([Math.random()*len|0], 1)[0]);
            len --;
        }
        return result;
    },
    lottery: function () {
        var args = Array.slice(arguments, 0).append([this]),
            counts = args.invoke('count'),
            balls = eval(counts.join('+')),
            len = Math.max.apply(0, counts),
            jLen = args.length,
            repeat = {},
            reduce = [],
            i = 0,
            j,
            num,
            total;
        for (; i < len; i++) {
            for (j = 0; j < jLen; j++) {
                num = args[j][i];
                if (num != undefined) {
                    repeat[num] = repeat[num] || [];
                    repeat[num].push(j);
                }
            }
        }
        total = eval(counts.join('*'));
        if (total) {
            Object.each(repeat, function (v, k) {
                if (v.length > 1) {
                    for (var i = 0, len = v.length, sum = balls; i < len; i++){
                        sum -= counts[v[i]];
                    }
                    reduce.push(sum);
                }
            });
            total -= reduce.length ? eval(reduce.join('+')) : 0;
        }
        return total;
    }
});

Element.implement({

	isDisplayed: function(){
		return this.offsetWidth && this.offsetHeight;
	},

	isVisible: function(){
		var w = this.offsetWidth,
			h = this.offsetHeight;
		return (w == 0 && h == 0) ? false: (w > 0 && h > 0) ? true: this.style.display != 'none';
	},

	visible: function(){
		return this.setStyle('visibility', 'visible');
	},

	hideit: function(){
		return this.setStyle('visibility', 'hidden');
	},

	toggle: function(){
		return this[this.isDisplayed() ? 'hide': 'block']();
	},

	hide: function(){
		var d;
		try {
			//IE fails here if the element is not in the dom
			d = this.getStyle('display');
		} catch(e){}
		if (d == 'none') return this;
		return this.store('element:_originalDisplay', d || '').setStyle('display', 'none');
	},

	block: function(){
		this.setStyle('display', 'block');
	},

	inline: function(){
		this.setStyle('display', 'inline');
	},

	show: function(display){
		if (!display && this.isDisplayed()) return this;
		display = display || this.retrieve('element:_originalDisplay') || 'inline';
		return this.setStyle('display', (display == 'none') ? 'inline': display);
	},

	swapClass: function(remove, add){
		return this.removeClass(remove).addClass(add);
	},

	hideOutline: function(){
		return Browser.ie ? this.set('hideFocus', 'true'): this.setStyle('outline', 'none');
	},

	central: function(){var win = window,w = {size: win.getSize(), scroll: win.getScroll()}, size = this.show().getSize();this.setStyles({position:'absolute',visibility: 'visible', left: Math.max(0, w.scroll.x + (w.size.x - size.x)/2), top: Math.max(0, w.scroll.y + (w.size.y - size.y)/2)});return this;}

});

Number.implement({
    currency: function(){
	    return this.toString().currency();
    },
    pad: function (n, c) {
        return (this + '').pad(n, c);
    },
    factorial: function () {
        var s = this.valueOf(),
            i = s;
        while (i -- > 1) {
            s *= i;
        }
        return s || 1;
    },
    combination: function (m) {
        return this.arrangement(this - m) / m.factorial();
    },
    arrangement: function (m) {
        var n = this.valueOf(),
            s = 1,
            i = n;
        while (i > m) {
            s *= i --;
        }
        return s;
    }
});

String.implement({
	currency: function(){
        return this.replace(/(\d)(?=(\d{3})+(\.|$))/g, '$1,');
	},
    pad: function (n, c, s, l) {
        n = n || 2;
        c = c || '0';
        s = this;
        l = s.length;
        return l >= n ? s.substr(l - n): new Array(n - l + 1).join(c) + s;
    },
	blength: function(){
		return this.replace(/[^\x00-\xff]|m/gi, '..').length;
	},
	cutString: function(len, append){
		var l = 0, i = 0, appendLen = 0, str = this;
		if(len >= str.blength()) return str;
        if(append) appendLen = append.blength();
		
		var rs = "";
		
		while(l < len){
			rs += str.charAt(i);
			l += str.charAt(i).blength();
			i ++;
		}
	
		if(l > len) rs = rs.substr(0, rs.length - 1);
		
		if(appendLen) {
            len -= appendLen;
            rs = rs.cutString(len) + append;
        }
		
		return rs;
	}
});

/**
 * 根据传入的命名空间路径创建对应object
 * @syntax using('Ku6.UI')
 * @param {String} p 要创建的命名空间路径，以半角点分隔
 * @return {Object} 创建好的命名空间对象
 */
function using(p){
	p = p.split(/\s*\.\s*/g);
	var m = window, d;
	p.each(function(n){
		if(d) d += '.' + n;
  		else d = n;
  		
		if(!m[n]) m[n] = { $name: d };
		else if(!m[n].$name) m[n].$name = d;
		
		m = m[n];
	});
	return m;
}

(function(ns, win, doc){

ns.JSONP = function(url, cache, sync){
	return new Element('script', {
        async: !sync, 
        type: 'text/javascript', 
        src: url + (url.indexOf('?') > 0 ? '&': '?') + (cache ? '': ('_=' + Date.now().toString(36)))
    }).inject(doc.head);
};

ns.Base = new Class({
	Implements: [Events, Options],
	options: {
		destroy: true, //页面unload前是否自动销毁
		wait: false    //是否等待domready后build
	},
	initialize: function(options){
		this.setOptions(options);
		var self = this,
			ops = self.options,
			build = function(){self.build(ops, self);self.binds();};
		this.bound = {};
		if(options && options.initialize) options.initialize.call(self);
		if(ops.wait) win.addEvent('domready', build);
		else build();
		if(ops.destroy) win.addEvent('beforeunload', self.destroy.bind(self));
	},
    binds: function(remove){
		var self = this,
			event = 'Event',
			action = (remove ? 'remove': 'add') + event,
			actions = action + 's';
		if(this.observe) this.observe(self, action, actions);
	},
	inject: function(el, where){
		(this.container || this.element).inject(el.container || el.element || el, where);
		return this;
	},
	grab: function(el, where){
		(this.container || this.element).grab(el, where);
		return this;
	},
	destroy: function(){
		win.removeEvent('beforeunload', arguments.callee);
		this.binds(true);
	}
});

})(using('HB'), this, document);
